package com.cskaoyan.mall.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.mall.cart.api.dto.CartInfoDTO;
import com.cskaoyan.mall.common.constant.RedisConst;
import com.cskaoyan.mall.common.constant.ResultCodeEnum;
import com.cskaoyan.mall.common.result.Result;
import com.cskaoyan.mall.common.util.DateUtil;
import com.cskaoyan.mall.mq.constant.MqTopicConst;
import com.cskaoyan.mall.mq.producer.BaseProducer;
import com.cskaoyan.mall.order.client.*;
import com.cskaoyan.mall.order.constant.OrderStatus;
import com.cskaoyan.mall.order.constant.OrderType;
import com.cskaoyan.mall.order.converter.CartInfoConverter;
import com.cskaoyan.mall.order.converter.OrderDetailConverter;
import com.cskaoyan.mall.order.converter.OrderInfoConverter;
import com.cskaoyan.mall.order.dto.OrderDetailDTO;
import com.cskaoyan.mall.order.dto.OrderInfoDTO;
import com.cskaoyan.mall.order.dto.OrderTradeDTO;
import com.cskaoyan.mall.order.mapper.OrderDetailMapper;
import com.cskaoyan.mall.order.mapper.OrderInfoMapper;
import com.cskaoyan.mall.order.model.OrderDetail;
import com.cskaoyan.mall.order.model.OrderInfo;
import com.cskaoyan.mall.order.query.OrderInfoParam;
import com.cskaoyan.mall.order.service.OrderService;
import com.cskaoyan.mall.pay.api.dto.PaymentInfoDTO;
import com.cskaoyan.mall.user.dto.UserAddressDTO;
import com.cskaoyan.mall.ware.api.constant.TaskStatus;
import com.cskaoyan.mall.ware.api.dto.WareOrderTaskDTO;
import com.cskaoyan.mall.ware.api.dto.WareSkuDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.OrderedBidiMap;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    ProductApiClient productApiClient;
    @Autowired
    CartApiClient cartApiClient;
    @Autowired
    UserApiClient userApiClient;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    WareApiClient wareApiClient;
    @Autowired
    PayApiClient payApiClient;
    @Autowired
    CartInfoConverter cartInfoConverter;
    @Autowired
    OrderInfoConverter orderInfoConverter;
    @Autowired
    OrderDetailConverter orderDetailConverter;
    @Autowired
    OrderDetailConverter detailConverter;
    @Autowired
    OrderInfoMapper orderInfoMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    BaseProducer baseProducer;

    /**确认订单，通过订单id获取结算页最终订单详情*/
    @Override
    public OrderTradeDTO getFinalOrderInfo(String userId) {
        // 1. 获取用户的地址列表信息 ——> 调用用户服务中的方法
        List<UserAddressDTO> addressList = userApiClient.findUserAddressListByUserId(userId);

        // 2. 获取待下单的商品列表
        List<CartInfoDTO> cartCheckedList = cartApiClient.getCartCheckedList(userId);
        // 待下单的购物车商品list ——> 订单明细列表
        List<OrderDetailDTO> orderDetailDTOS
                = cartInfoConverter.convertCartInfoDTOToOrderDetailDTOList(cartCheckedList);

        // 3. 计算待下单的商品总数量
        int total = cartCheckedList.stream().mapToInt(CartInfoDTO::getSkuNum).sum();

        // 4. 计算总金额
        OrderInfoDTO orderInfoDTO = new OrderInfoDTO();
        orderInfoDTO.setOrderDetailList(orderDetailDTOS);
        // 利用OrderInfoDTO的sumTotalAmount方法计算订单总金额
        orderInfoDTO.sumTotalAmount();
        // 获取到订单总金额
        BigDecimal totalAmount = orderInfoDTO.getTotalAmount();

        // 封装包含详情页数据的OrderTradeDTO对象
        OrderTradeDTO orderTradeDTO = new OrderTradeDTO();
        orderTradeDTO.setUserAddressList(addressList);
        orderTradeDTO.setDetailArrayList(orderDetailDTOS);
        orderTradeDTO.setTotalNum(total);
        orderTradeDTO.setTotalAmount(totalAmount);

        return orderTradeDTO;
    }

    /**
     * 提交订单: 校验价格
     */
    @Override
    public Boolean checkPrice(Long skuId, BigDecimal skuPrice) {

        BigDecimal nowPrice = productApiClient.getSkuPrice(skuId);
        if (nowPrice.compareTo(skuPrice) != 0) {
            return true;
        }
        // 相等
        return false;
    }

    /**
     * 提交订单: 保存订单以及订单详情
     */
    @Override
    @Transactional    // 事务注解，保证事务的一致性
    public Long saveOrderInfo(OrderInfo orderInfo) {
        // 设置一些订单数据
        buildOrderInfo(orderInfo);

        // 保存订单信息(order_info，order_detail)  todo

        // 购物车服务中删除购物车中已经下单的商品 todo
        List<Long> skuIds = orderInfo.getOrderDetailList().stream()
                .map(orderDetail -> orderDetail.getSkuId()).collect(Collectors.toList());
        cartApiClient.removeCartProductsInOrder(orderInfo.getUserId().toString(), skuIds);

        // 发送延迟消息  （消息主题，消息内容，延迟级别）
        baseProducer.sendDelayMessage(MqTopicConst.DELAY_ORDER_TOPIC, orderInfo.getId(), MqTopicConst.DELAY_ORDER_LEVEL);

        // 返回订单id
        return orderInfo.getId();
    }

    /**.01 构建订单信息*/
    private void buildOrderInfo(OrderInfo orderInfo) {
        // 计算总金额
        orderInfo.sumTotalAmount();
        // 订单状态 - 未支付
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        // 第三方订单编号     自定义字段 + 时间戳 + 随机数
        String outTradeNo = "CSKAOYAN" + System.currentTimeMillis() + new Random().nextInt(1000);
        // 订单号
        orderInfo.setOutTradeNo(outTradeNo);
        // 获取订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuffer stringBuffer = new StringBuffer();
        for (OrderDetail orderDetail : orderDetailList) {
            String skuName = orderDetail.getSkuName() + "  ";
            stringBuffer.append(skuName);   // 把所有商品名称拼在一起
        }
        // 订单商品描述 - 判断字符串长度是否大于100，如果大于100，则截取前100个字符；否则，直接使用
        String tradeBody = stringBuffer.toString().length() > 100 ? stringBuffer.toString().substring(0, 100) :
                stringBuffer.toString();
        orderInfo.setTradeBody(tradeBody);
    }

    /**
     * 我的订单：获取 "我的订单" 列表
     */
    @Override
    public IPage<OrderInfoDTO> getPage(Page<OrderInfoDTO> pageParam, String userId) {
        IPage<OrderInfoDTO> orderInfoDTOIPage = orderInfoMapper.selectPageByUserId(pageParam, userId);
        orderInfoDTOIPage.getRecords().forEach(orderInfoDTO -> {
            // 获取订单状态对应的中文描述字符串，设置orderInfoDTO的orderStatusName
            orderInfoDTO.setOrderStatusName(OrderStatus.getStatusDescByStatus(orderInfoDTO.getOrderStatus()));
        });
        return orderInfoDTOIPage;
    }

    /**
     * 秒杀服务中，提交秒杀订单
     */
    @Override
    @Transactional
    public Long saveSeckillOrder(OrderInfoParam orderInfoParam) {
        OrderInfo orderInfo = orderInfoConverter.convertOrderInfoParam(orderInfoParam);
        buildSeckillOrder(orderInfo);
        orderInfoMapper.insert(orderInfo);

        for (OrderDetail orderDetail : orderInfo.getOrderDetailList()) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
        return orderInfo.getId();
    }
/**构造秒杀订单信息*/
    private void buildSeckillOrder(OrderInfo orderInfo) {
        orderInfo.setOrderType(OrderType.PROMO_ORDER.name());
        orderInfo.sumTotalAmount();

        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        String outTradeNo = "CSKAOYAN_SECKILL"+System.currentTimeMillis()+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);

        OrderDetail orderDetail = orderInfo.getOrderDetailList().get(0);
        orderInfo.setTradeBody(orderDetail.getSkuName());
    }

    /**
     * 提交订单: 更新用户购物车商品价格
     */
    @Override
    public void refreshPrice(Long skuId, String userId) {

    }



    /**
     * 支付回调：支付成功，修改订单状态
     */
    @Override
    public void successPay(Long orderId) {
        updateOrderStatus(orderId, OrderStatus.PAID.name());
    }

    /**
     * 支付回调：库存扣减完成，修改订单状态
     */
    @Override
    public void successLockStock(String orderId, String taskStatus) {
        if (TaskStatus.DEDUCTED.name().equals(taskStatus)) {
            // 锁定库存成功
            updateOrderStatus(Long.parseLong(orderId), OrderStatus.WAIT_DELEVER.name());
        } else {
            // 锁定库存失败，返回异常
            updateOrderStatus(Long.parseLong(orderId), OrderStatus.STOCK_EXCEPTION.name());
        }
    }

    /**
     * 支付回调：拆单
     */
    @Override
    public List<WareOrderTaskDTO> orderSplit(String orderId, List<WareSkuDTO> wareSkuDTOList) {
        List<WareOrderTaskDTO> result = new ArrayList<>();
        // 1 判断异常情况，如果 orderId 或 wareSkuDTOList 为空，则直接返回空
        if (StringUtils.isEmpty(orderId) || CollectionUtils.isEmpty(wareSkuDTOList)) {
            return result;
        }
        // 2 拆单
        // 2.1 查询出原来待拆单的订单
        long id = Long.parseLong(orderId);
        OrderInfoDTO oldOrderInfo = getOrderInfo(id);
        // 2.2 获取遍历原订单的订单商品条目
        List<OrderDetailDTO> orderDetailList = oldOrderInfo.getOrderDetailList();
        // 2，3 遍历拆单 依据wareSkuDTOList
        for (WareSkuDTO wareSkuDTO : wareSkuDTOList) {
            // 当前仓库id
            String wareId = wareSkuDTO.getWareId();
            // 包含当前仓库中的商品id集合
            List<String> skuIds = wareSkuDTO.getSkuIds();

            // 2.4 构建子订单
            OrderInfo subOrderInfo = orderInfoConverter.copyOrderInfo(oldOrderInfo);
            subOrderInfo.setId(null);
            // 父订单id
            subOrderInfo.setParentOrderId(oldOrderInfo.getId());
            // 设置仓库id
            subOrderInfo.setWareId(wareId);

            // 2.5 构建子订单包含的订单商品列表
            List<OrderDetail> orderDetails = new ArrayList<>();
            for (OrderDetailDTO orderDetailDTO : orderDetailList) {
                // 不使用之前的id插入
                orderDetailDTO.setId(null);
                if (skuIds.contains(orderDetailDTO.getSkuId().toString())) {
                    // 如果订单商品条目属于当前仓库中包含的商品，该条目属于当前子订单的条目
                    orderDetails.add(orderDetailConverter.convertOrderDetailToDTO(orderDetailDTO));
                }
            }
            // 设置子订单的明细列表
            subOrderInfo.setOrderDetailList(orderDetails);
            // 2.6 保存子订单
            saveSubOrder(subOrderInfo);

            // 2.7 将子订单转化为一个库存工作单
            WareOrderTaskDTO wareOrderTaskDTO = orderInfoConverter.convertOrderInfoToWareOrderTaskDTO(subOrderInfo);
            result.add(wareOrderTaskDTO);
        }
        // 2.8 将原订单的状态改为拆单状态
        updateOrderStatus(Long.parseLong(orderId),OrderStatus.SPLIT.name());
        return result;
    }

    /**
     * API: 根据订单id获取订单信息
     */
    @Override
    public OrderInfoDTO getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo == null) return null;
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);

        List<OrderDetail> orderDetails = orderDetailMapper.selectList(queryWrapper);
        orderInfo.setOrderDetailList(orderDetails);

        // 转化
        OrderInfoDTO orderInfoDTO = orderInfoConverter.convertOrderInfoToOrderInfoDTO(orderInfo);
        return orderInfoDTO;
    }

    /**
     * API：通过orderId找到订单信息，更新订单状态
     */
    private void updateOrderStatus(Long orderId, String orderStatus) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        orderInfo.setOrderStatus(orderStatus);
        orderInfoMapper.updateById(orderInfo);
    }

    /**
     * 保存子订单
     */
    private void saveSubOrder(OrderInfo subOrderInfo) {
        // 构建子订单信息
        buildSubOrder(subOrderInfo);
        // 保存子订单
        orderInfoMapper.insert(subOrderInfo);
        // 保存子订单的订单明细
        List<OrderDetail> orderDetailList = subOrderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            // 设置子订单明细，所属的子订单id
            orderDetail.setOrderId(subOrderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
    }

    /**
     * 构建子订单信息
     */
    private void buildSubOrder(OrderInfo subOrderInfo) {
        // 计算总金额
        subOrderInfo.sumTotalAmount();
        // 订单状态
        subOrderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        // 第三方订单编号
        String outTradeNo = "CSKAOYAN" + System.currentTimeMillis() + new Random().nextInt(1000);
        // 订单号
        subOrderInfo.setOutTradeNo(outTradeNo);
        // 获取订单明细
        List<OrderDetail> orderDetailList = subOrderInfo.getOrderDetailList();
        StringBuffer stringBuffer = new StringBuffer();
        for (OrderDetail orderDetail : orderDetailList) {
            String skuName = orderDetail.getSkuName() + "  ";
            stringBuffer.append(skuName);
        }
        String tradeBody = stringBuffer.toString().length() > 100 ? stringBuffer.toString().substring(0, 100) :
                stringBuffer.toString();
        subOrderInfo.setTradeBody(tradeBody);
    }

    /**
     * 订单超时取消
     */
    @Override
    public void execExpiredOrder(Long orderId) {
        // todo 处理超时订单
    }
}
